package com.tianji.aigc.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.convert.Convert;
import cn.hutool.json.JSONArray;
import cn.hutool.json.JSONObject;
import com.alibaba.cloud.ai.dashscope.audio.synthesis.SpeechSynthesisModel;
import com.alibaba.cloud.ai.dashscope.audio.synthesis.SpeechSynthesisPrompt;
import com.alibaba.cloud.ai.dashscope.audio.synthesis.SpeechSynthesisResponse;
import com.alibaba.dashscope.audio.asr.recognition.Recognition;
import com.alibaba.dashscope.audio.asr.recognition.RecognitionParam;
import com.tianji.aigc.service.AudioService;
import com.tianji.common.exceptions.CommonException;
import com.tianji.common.utils.JsonUtils;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.servlet.mvc.method.annotation.ResponseBodyEmitter;
import reactor.core.publisher.Flux;

import java.io.File;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * @author wys
 * @version V1.0
 * @date 2025-04-26 20:04
 */
@Service
@RequiredArgsConstructor
@Slf4j
public class DashScopeAudioServiceImpl implements AudioService {
    private final SpeechSynthesisModel speechSynthesisModel;

    /**
     * 文字转语音（TTS）
     *
     * @param text 待合成的文本内容
     * @return 异步响应输出
     */
    @Override
    public ResponseBodyEmitter ttsStream(String text) {
        ResponseBodyEmitter emitter = new ResponseBodyEmitter();
        log.info("开始语音合成, 文本内容：{}", text);

        Flux<SpeechSynthesisResponse> response = speechSynthesisModel.stream(
                new SpeechSynthesisPrompt(text)
        );
        response.subscribe(
                synthesisResponse -> {
                    try {
                        // 获取响应输出的数据，并发送到响应体中
                        ByteBuffer byteBuffer = synthesisResponse.getResult().getOutput().getAudio();
                        byte[] bytes = new byte[byteBuffer.remaining()];
                        byteBuffer.get(bytes);
                        emitter.send(bytes);
                    } catch (IOException e) {
                        emitter.completeWithError(e);
                    }
                },
                emitter::completeWithError,
                emitter::complete
        );
        return emitter;
    }

    /**
     * 语音转文字（STT）
     *
     * @param audioFile 音频文件
     * @return 识别结果文本
     */
    @Override
    public String stt(MultipartFile audioFile) {
        // 创建Recognition实例
        Recognition recognizer = new Recognition();
        // 创建RecognitionParam
        RecognitionParam param =
                RecognitionParam.builder()
                        // 若没有将API Key配置到环境变量中，需将下面这行代码注释放开，并将apiKey替换为自己的API Key
                        // .apiKey("yourApikey")
                        .model("paraformer-realtime-v2")
                        .format("mp3")
                        .sampleRate(24000)
                        .build();
        File tempFile = null;
        try {
            tempFile = File.createTempFile("uploaded-", "-" + audioFile.getOriginalFilename());
            // 将字节流包装为资源对象
            // 将 MultipartFile 写入临时文件
            audioFile.transferTo(tempFile);
            String call = recognizer.call(param, tempFile);
            JSONObject jsonObject = JsonUtils.parseObj(call);
            String jsonArrayStr = jsonObject.getStr("sentences");
            JSONArray jsonArray = JsonUtils.parseArray(jsonArrayStr);
            return jsonArray.stream()
                    .map(object -> Convert.toStr(BeanUtil.toBean(object, Map.class).get("text")))
                    .collect(Collectors.joining());

        } catch (Exception e) {
            log.error("{}", e);
            throw new CommonException("识别失败");
        } finally {
            if (tempFile != null) {
                tempFile.delete();
            }
        }
    }
}
